// 腾讯云语音识别工具
const request = require('../request');
const keywordExtractor = require('../keyword');
const asrLogger = require('./asrLogger');
const { v4: uuidv4 } = require('../../lib/uuid'); // 假设已引入UUID库，如果没有请安装

/**
 * 腾讯云语音识别服务
 * 实现微信小程序与腾讯云ASR服务的对接
 */
const tencentAsr = {
  // 腾讯云API密钥信息 (需要传递给云函数)
  secretId: 'AKIDISQDnAJEwSlqiNr7A1f6JL9lAMM9j7HD', // 确保这里是你自己的 SecretId
  secretKey: 'mJckeLp6HGSaYJ2hEbljU7WigT3FEzXt', // 确保这里是你自己的 SecretKey
  isInitialized: false,
  cloudEnvId: 'cloud1-7g7dx7zy6c408dd3', // 需要设置你的云环境ID
  cloudFunctionName: 'generateSignature', // 需要设置你的云函数名称
  /**
   * 初始化配置
   * @param {Object} config 配置对象
   */
  init(config) {
    this.isInitialized = true;
    if (config.secretId) this.secretId = config.secretId;
    if (config.secretKey) this.secretKey = config.secretKey;
    if (config.cloudEnvId) this.cloudEnvId = config.cloudEnvId;

    // 初始化ASR日志
    asrLogger.init();
    asrLogger.info('腾讯云ASR服务初始化', {
      hasSecretId: !!this.secretId,
      hasSecretKey: !!this.secretKey,
      cloudEnvId: this.cloudEnvId
    });

    // 初始化云开发（如果未在 app.js 初始化）
    if (wx.cloud && !wx.cloud.inited) {
      try {
        wx.cloud.init({ env: this.cloudEnvId, traceUser: true });
        asrLogger.info('微信云开发初始化成功', { env: this.cloudEnvId });
      } catch (err) {
        asrLogger.error('微信云开发初始化失败', { error: err, env: this.cloudEnvId });
      }
    }
  },

  /**
   * 调用云函数生成签名和请求头
   * @param {Object} params 请求参数 (例如 ASR 的 Data, VoiceFormat 等)
   * @param {string} action API Action (例如 'SentenceRecognition')
   * @param {string} version API Version (例如 '2019-06-14')
   * @returns {Promise<Object>} 包含签名后完整请求头的 Promise 对象
   */
  async generateSignatureAndHeaders(params, action, version) {
    const requestId = uuidv4();
    asrLogger.info(requestId, '调用云函数生成签名', { action });

    if (!this.secretId || !this.secretKey) {
      asrLogger.error(requestId, '缺少 SecretId 或 SecretKey，无法生成签名');
      throw new Error('缺少API密钥');
    }
    if (!wx.cloud) {
      asrLogger.error(requestId, '微信云开发未初始化或不可用');
      throw new Error('云开发不可用');
    }

    try {
      const result = await wx.cloud.callFunction({
        name: 'generateSignature', // 确保云函数名称正确
        data: {
          params: { ...params, Action: action, Version: version }, // 将 Action 和 Version 传递给云函数内部构建 params
          secretId: this.secretId,
          secretKey: this.secretKey,
          region: 'ap-guangzhou', // 根据你的服务区域调整
          endpoint: 'asr.tencentcloudapi.com'
        }
      });

      if (result.result && result.result.success) {
        asrLogger.info(requestId, '云函数签名成功');
        return result.result.headers; // 返回完整的请求头对象
      } else {
        const errorMsg = result.result && result.result.error ? result.result.error : '未知云函数错误';
        asrLogger.error(requestId, '云函数签名失败', { error: errorMsg });
        throw new Error(`云函数签名失败: ${errorMsg}`);
      }
    } catch (error) {
      asrLogger.error(requestId, '调用云函数异常', { error });
      throw error; // 将错误继续抛出
    }
  },

  /**
   * 语音识别方法
   * @param {string} tempFilePath 录音文件临时路径
   * @returns {Promise<string>} 识别后的文本结果
   */
  async recognize(tempFilePath) {
    // 使用 async/await 重写
    const requestId = uuidv4();
    asrLogger.info(requestId, '开始语音识别流程', { tempFilePath });

    if (!this.isInitialized) {
      asrLogger.warn(requestId, '服务未初始化，将使用默认配置');
      // 考虑是否应该在此处 reject 或强制初始化
    }

    const fileManager = wx.getFileSystemManager();

    try {
      // 1. 获取文件信息
      const fileInfo = await new Promise((resolve, reject) => {
        wx.getFileInfo({
          filePath: tempFilePath,
          success: resolve,
          fail: reject
        });
      });
      const fileSize = fileInfo.size;
      asrLogger.logAudioInfo(tempFilePath, fileInfo.duration || '未知', fileSize);

      // 2. 读取文件内容 (Base64)
      const fileRes = await new Promise((resolve, reject) => {
        fileManager.readFile({
          filePath: tempFilePath,
          encoding: 'base64',
          success: resolve,
          fail: reject
        });
      });
      const voiceData = fileRes.data;

      // 3. 准备请求参数
      const action = 'SentenceRecognition';
      const version = '2019-06-14';
      const requestParams = {
        EngineModelType: '16k_zh',
        VoiceFormat: 'mp3',
        Data: voiceData // 将完整的 Base64 数据传递给云函数签名
      };

      asrLogger.debug(requestId, '准备调用签名云函数', { action });

      // 4. 调用云函数获取签名和请求头
      const headers = await this.generateSignatureAndHeaders(requestParams, action, version);
      asrLogger.info(requestId, '获取签名后的请求头成功');

      // 5. 记录请求日志（省略 Base64 数据）
      const logParams = { ...requestParams, Data: '(BASE64数据)' };
      asrLogger.logRequest(requestId, {
        url: `https://${headers.Host}`, // 从返回的 headers 获取 Host
        method: 'POST',
        action: action,
        version: version,
        region: headers['X-TC-Region'], // 从返回的 headers 获取 Region
        headers: headers, // 记录完整的头信息
        params: logParams,
        fileSize: fileSize
      });

      // 6. 发起腾讯云ASR请求
      const result = await new Promise((resolve, reject) => {
        wx.request({
          url: `https://${headers.Host}`, // 使用云函数返回的 Host
          method: 'POST',
          data: requestParams, // 发送包含完整 Base64 数据的参数
          header: headers, // 使用云函数返回的完整请求头
          success: resolve,
          fail: reject
        });
      });
      asrLogger.debug(requestId, 'ASR API 请求成功返回');

      // 7. 处理响应
      if (result.statusCode === 200 && result.data && result.data.Response) {
        if (result.data.Response.Error) {
          // API 返回业务错误
          const error = result.data.Response.Error;
          const errorMessage = `语音识别失败: ${error.Message} (${error.Code})`;
          asrLogger.logResponse(requestId, { statusCode: result.statusCode, isSuccess: false, error: error });
          asrLogger.error(requestId, errorMessage, error);
          throw new Error(errorMessage);
        } else {
          // 成功获取识别结果
          const recognizedText = result.data.Response.Result || '';
          const responseTime = Date.now();
          asrLogger.logResponse(requestId, { statusCode: result.statusCode, isSuccess: true, resultLength: recognizedText.length });
          asrLogger.logRecognitionResult(requestId, recognizedText, responseTime);
          asrLogger.info(requestId, '语音识别成功', { text: recognizedText });
          return recognizedText; // 返回结果
        }
      } else {
        // HTTP 错误或其他未知错误
        const errorMsg = `语音识别请求失败，状态码: ${result.statusCode}`;
        asrLogger.logResponse(requestId, { statusCode: result.statusCode, isSuccess: false, responseData: result.data });
        asrLogger.error(requestId, errorMsg, { response: result });
        throw new Error(errorMsg);
      }

    } catch (error) {
      // 统一处理流程中的所有错误
      const errMsg = error.errMsg || (error.message ? error.message : '未知错误');
      asrLogger.error(requestId, `语音识别流程异常: ${errMsg}`, { error });
      // 根据需要决定是否再次抛出错误，或者返回一个默认值/错误标识
      throw error; // 将错误继续向上抛出，让调用者处理
    }
  },

  /**
   * 语音识别并提取关键词
   * @param {string} tempFilePath 录音文件临时路径
   * @returns {Promise<Object>} 包含 text 和 keyword 的对象
   */
  async recognizeAndExtractKeyword(tempFilePath) {
    const requestId = uuidv4();
    asrLogger.info(requestId, '开始语音识别并提取关键词');
    try {
      const recognizedText = await this.recognize(tempFilePath);
      // 使用关键词提取器提取关键词
      const keyword = keywordExtractor.extractFromVoice(recognizedText);
      // 记录关键词提取结果
      asrLogger.logKeywords(recognizedText, keyword);
      asrLogger.info(requestId, '关键词提取成功', { keyword });
      return {
        text: recognizedText,
        keyword: keyword
      };
    } catch (err) {
      asrLogger.error(requestId, '语音识别并提取关键词失败', { error: err.message || err });
      throw err; // 继续抛出错误
    }
  },

  /**
   * 测试ASR服务连接 (通过调用云函数测试签名间接测试)
   * @returns {Promise<boolean>} 测试结果
   */
  async testConnection() {
    const requestId = 'test-connection-' + Date.now();
    asrLogger.info(requestId, '测试腾讯云ASR服务连接 (通过测试签名云函数)');

    try {
      // 尝试调用云函数生成一个简单的签名来测试连接和配置
      const headers = await this.generateSignatureAndHeaders({}, 'DescribeTaskStatus', '2019-06-14');
      // 如果能成功获取 headers，说明云函数调用正常，配置也基本可用
      const isSuccess = !!headers;
      asrLogger.info(requestId, `连接测试${isSuccess ? '成功' : '失败'} (云函数调用)`, { success: isSuccess });
      return isSuccess;
    } catch (error) {
      asrLogger.error(requestId, '连接测试请求失败 (云函数调用)', { error: error.message || error });
      return false;
    }
  },

  /**
   * 获取ASR服务日志
   * @param {number} [maxLines=100] 最大返回行数
   * @returns {Array<Object>} 日志对象数组
   */
  getServiceLogs(maxLines = 100) {
    // 直接从 asrLogger 获取
    return asrLogger.getLogs(maxLines);
  },

  /**
   * 清空ASR日志
   */
  clearLogs() {
    asrLogger.clearLogs();
  }
};

module.exports = tencentAsr;